/*
 * frxs Inc.  湖南兴盛优选电子商务有限公司.
 * Copyright (c) 2017-2019. All Rights Reserved.
 */
package util;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.ServiceLoader;

/**
 * 序列化 工具类
 * @author luozhiwei
 * @version : SerializeUtils.java,v 0.1 2021年05月13日 11:12
 */
public class SerializeUtils {

	/**
	 * protostuff序列化名称
	 */
	public static final String PROTOSTUFF_SERIALIZATION = "protostuff";

	private static final Map<String, SerializeService> SERIALIZE_SERVICE_MAP = new HashMap<>();

	static {
		ServiceLoader<SerializeService> serviceLoader = ServiceLoader.load(SerializeService.class);
		serviceLoader.forEach(serializeService -> SERIALIZE_SERVICE_MAP.put(serializeService.getSerialization(), serializeService));
	}

	/**
	 * 获取序列化实现类
	 *
	 * @param serialization 序列化方式
	 * @return 序列化实现类
	 */
	public static Optional<SerializeService> getSerializeService(String serialization) {
		return Optional.ofNullable(SERIALIZE_SERVICE_MAP.get(serialization));
	}

	/**
	 * 获取body
	 *
	 * @param body 字节数组
	 * @param targetClass 目标对象的类对象
	 * @param serializeName 序列化方式
	 * @return 响应结果
	 */
	public static <T> T deserialize(byte[] body, Class<T> targetClass, String serializeName) {
		return SerializeUtils.getSerializeService(serializeName).orElseThrow(() -> new NoClassDefFoundError("can not find serializeService impl!"))
				.deserializeWithBytes(body, targetClass);
	}

	/**
	 * 获取body
	 *
	 * @param body 字节数组
	 * @param targetClass 目标对象的类对象
	 * @param serializeName 序列化方式
	 * @return 响应结果
	 */
	public static <T> T deserialize(byte[] body, Class<T> targetClass) {
		return deserialize(body, targetClass, PROTOSTUFF_SERIALIZATION);
	}

	/**
	 * 当前DTO的序列化方式
	 *
	 * @param <T> target
	 * @param serializeName 序列化方式
	 * @return 响应结果
	 */
	public static <T> byte[] serialize(T target, String serializeName) {
		return SerializeUtils.getSerializeService(serializeName).orElseThrow(() -> new NoClassDefFoundError("can not find serializeService impl!"))
				.serializeToBytes(target);
	}

	/**
	 * 当前DTO的序列化方式
	 *
	 * @param <T> target
	 * @param serializeName 序列化方式
	 * @return 响应结果
	 */
	public static <T> byte[] serialize(T target) {
		return serialize(target, PROTOSTUFF_SERIALIZATION);
	}
}